package cn.yunlang.zhangZhongFei.service.impl;

import cn.hutool.crypto.digest.DigestUtil;
import cn.yunlang.zhangZhongFei.util.PasswordUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import cn.yunlang.zhangZhongFei.constant.AuthenticationConstants;
import cn.yunlang.zhangZhongFei.entity.SysUser;
import cn.yunlang.zhangZhongFei.entity.User;
import cn.yunlang.zhangZhongFei.entity.req.WxCodeReq;
import cn.yunlang.zhangZhongFei.exception.ErrorCodeException;
import cn.yunlang.zhangZhongFei.mapper.UserMapper;
import cn.yunlang.zhangZhongFei.service.LoginService;
import cn.yunlang.zhangZhongFei.service.SysUserService;
import cn.yunlang.zhangZhongFei.util.CheckEmptyUtil;
import cn.yunlang.zhangZhongFei.util.JwtUtil;
import cn.yunlang.zhangZhongFei.util.RedisUtil;
import cn.yunlang.zhangZhongFei.vo.response.LoginResponseVo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.lettuce.core.RedisClient;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;

/**
 * @author yyl25
 */
@Slf4j
@Service
public class LoginServiceImpl implements LoginService {
    @Value("${wx.appId}")
    private String wxAppId;

    @Value("${wx.appSecret}")
    private String wxSecret;

    @Resource
    private UserMapper userMapper;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private AuthenticationManager authenticationManager;
    @Autowired
    private SysUserService sysUserService;

    @Override
    public String loginWeixin(WxCodeReq req) {
        JSONObject jsonResponse = new JSONObject();
        String code = req.getCode();
        try {
            String url =
                    "https://api.weixin.qq.com/sns/jscode2session?appid="
                            + URLEncoder.encode(wxAppId, "UTF-8")
                            + "&secret="
                            + URLEncoder.encode(wxSecret, "UTF-8")
                            + "&js_code="
                            + URLEncoder.encode(code, "UTF-8")
                            + "&grant_type=authorization_code";

            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setRequestMethod("GET");
            connection.setRequestProperty("Accept", "application/json");

            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String inputLine;
                StringBuilder response = new StringBuilder();

                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                in.close();

                // 解析返回的 JSON
                jsonResponse = JSONObject.parseObject(response.toString());
            } else {
                log.error("GET请求失败，响应代码：" + responseCode);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("请求失败");
        }
        String openid = jsonResponse.getString("openid");
        if (StringUtils.isBlank(openid)) {
            String errmsg = "错误：" + jsonResponse.getString("errcode");
            return errmsg;
        }
        return openid;
    }



    /**
     * eq(column, value): 等于
     * ne(column, value): 不等于
     * gt(column, value): 大于
     * ge(column, value): 大于等于
     * lt(column, value): 小于
     * le(column, value): 小于等于
     * like(column, value): 模糊查询
     * notLike(column, value): 不模糊查询
     * in(column, valueList): 在指定集合中
     * notIn(column, valueList): 不在指定集合中
     * isNull(column): 为空
     * isNotNull(column): 不为空
     * orderByAsc(column): 升序排序
     * orderByDesc(column): 降序排序
     * 注册用户信息与获取用户信息详情
     */
    @Override
    public LoginResponseVo userLogin(String openId) {
        User userDetails =
                userMapper.selectOne(

                        new LambdaQueryWrapper<User>().eq(openId != null, User::getOpenId, openId)

                );
        // 用户不存在 进行 注册
        if (CheckEmptyUtil.isEmpty(userDetails)) {
            log.info("新用户：[{}],注册", openId);
            User user = new User();
            user.setOpenId(openId);
            user.setNickName("新用户");
            userMapper.insert(user);
            return createLogVo(user.getId().longValue());
        } else {
            log.info("用户：[{}]根据用户信息查询的用户详情：[{}]", openId, userDetails);
            return createLogVo(userDetails.getId().longValue());
        }
    }


    @Override
    public String getPhone(WxCodeReq req) {
        String code = req.getCode();
        Long userId = Long.valueOf(new JwtUtil().getUserId());
        String phone = getPhone(code);
        User user = new User();
        user.setId(userId);
        user.setPhone(phone);
        //将手机号更新到用户信息中
        userMapper.updateById(user);
        return phone;
    }


    private String getPhone(String code) {
        String phoneNumber = "";
        JSONObject jsonResponse = new JSONObject();
        String accessToken = getToken();
        String jsonInputString = "{\"code\":\"" + code + "\"}"; // 替换为您的用户code

        try {
            String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken;
            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setDoOutput(true);
            log.info("getPhone:{}", jsonInputString);
            // 发送请求
            try (DataOutputStream wr = new DataOutputStream(connection.getOutputStream())) {
                wr.writeBytes(jsonInputString);
                wr.flush();
            }

            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String inputLine;
                StringBuilder response = new StringBuilder();

                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                in.close();
                // 解析返回的 JSON
                jsonResponse = JSONObject.parseObject(response.toString());
                log.info("getPhone:{}", jsonResponse.toJSONString());
            } else {
                log.error("POST请求失败，响应代码：" + responseCode);
                throw new RuntimeException("POST请求失败，响应代码：" + responseCode);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            phoneNumber = JSONObject.parseObject(jsonResponse.getString("phone_info")).getString("phoneNumber");
            if (StringUtils.isBlank(phoneNumber)) {
                String errmsg = "错误：" + jsonResponse.getString("errcode");
                return errmsg;
            }
        } catch (Exception e) {
            log.error("获取手机号异常" + jsonResponse.toJSONString());
            throw new RuntimeException("获取手机号异常");
        }
        return phoneNumber;
    }

    public String getToken() {
        String token = null;
        try {
            String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" +
                    "&appid=" + URLEncoder.encode(wxAppId, "UTF-8") +
                    "&secret=" + URLEncoder.encode(wxSecret, "UTF-8");

            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setRequestMethod("GET");
            connection.setRequestProperty("Accept", "application/json");

            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String inputLine;
                StringBuilder response = new StringBuilder();

                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                in.close();

                // 解析返回的 JSON
                JSONObject jsonResponse = JSONObject.parseObject(response.toString());
                token = jsonResponse.getString("access_token");
            } else {
                System.out.println("请求失败，响应代码：" + responseCode);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return token;
    }

    @Override
    public LoginResponseVo sysLogin(SysUser user) {

        SysUser sysUser =
                sysUserService.getOne(  new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, user.getUsername()));
        System.out.println("mlogin"+sysUser);
        // md5加密比较
        if (DigestUtil.md5Hex(user.getPassword()).equals(sysUser.getPassword())) {

            LoginResponseVo loginResponseVo = new LoginResponseVo();
            String token = new JwtUtil().createJWT(sysUser.getId().toString());
            loginResponseVo.setUserId(sysUser.getId());
            loginResponseVo.setToken(token);
            loginResponseVo.setType(0);
            sysUser.setToken(token);
            String redisUserTokenKey =
                    AuthenticationConstants.BACKSTAGE_USER_LOGIN_TOKEN + sysUser.getId();
            System.out.println("mlogin++++++++   :"+sysUser.getToken());
            redisUtil.set(redisUserTokenKey, JSON.toJSONString(sysUser));


        /*    RedisClient redisClient = RedisClient.create("redis://localhost:6379");
            StatefulRedisConnection<String, String> connection = redisClient.connect();


            // 从Redis获取并反序列化
            RedisCommands<String, String> syncCommands = connection.sync();
            String retrievedJson = syncCommands.get(redisUserTokenKey);




            try {
                ObjectMapper objectMapper = new ObjectMapper();
                SysUser sysUserRedis = objectMapper.readValue(retrievedJson, SysUser.class);
                String redisToken=sysUserRedis.getToken();
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }*/


            System.out.println("mlogin"+sysUser);
            return loginResponseVo;
        }
        throw new ErrorCodeException(500, "登录失败！请检查用户名&密码");
    }

    @NotNull
    private LoginResponseVo createLogVo(Long userId) {
        LoginResponseVo loginResponseVo = new LoginResponseVo();
        String token = new JwtUtil().createJWT(userId.toString());
        loginResponseVo.setUserId(userId);
        loginResponseVo.setToken(token);
        loginResponseVo.setType(1);
        String redisUserTokenKey = AuthenticationConstants.USER_LOGIN_TOKEN + userId;
        redisUtil.set(redisUserTokenKey, token);
        return loginResponseVo;
    }

    @Override
    public void logout() {
        redisUtil.del(AuthenticationConstants.BACKSTAGE_USER_LOGIN_TOKEN + new JwtUtil().getUserId());
    }

    @Override
    public LoginResponseVo backLogin(User user) {
        User userDetail =
                userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getPhone, user.getPhone()));
        if (CheckEmptyUtil.isEmpty(userDetail)) {
            // 不存在
            userMapper.insert(user);
            return createLogVo(user.getId().longValue());
        }
        // 存在用户
        return createLogVo(userDetail.getId().longValue());
    }

}
